#pragma once
#include "Binding/BoundAssignment.hpp"
#include "Binding/BoundBinary.hpp"
#include "Binding/BoundBlock.hpp"
#include "Binding/BoundExpression.hpp"
#include "Binding/BoundExpressionStatement.hpp"
#include "Binding/BoundForStatement.hpp"
#include "Binding/BoundIfStatement.hpp"
#include "Binding/BoundLiteral.hpp"
#include "Binding/BoundUnary.hpp"
#include "Binding/BoundVariable.hpp"
#include "Binding/BoundVariableDeclaration.hpp"
#include "Binding/BoundWhileStatement.hpp"
#include "Symbols/VariableMap.hpp"


class Evaluator
{
public:
    Evaluator(SharedBoundBlockStatement root, SharedVariableMap variable) : Root(root), Variables(variable), LastValue(nullptr) {}

    SharedObject Evaluate();
    // {
    //     this->EvaluateStatement(this->Root);
    //     return this->LastValue;
    // }

private:
    SharedObject EvaluateExpression(SharedBoundExpression node);
    SharedObject EvaluateUnaryExpression(BoundUnaryExpression *unary);
    SharedObject EvaluateBinaryExpression(BoundBinaryExpression *binary);
    SharedObject EvaluateLiteralExpression(BoundLiteralExpression *literal);
    SharedObject EvaluateVariableExpression(BoundVariableExpression *variable);
    SharedObject EvaluateAssignmentExpression(BoundAssignmentExpression *assignment);

    void EvaluateExpressionStatement(BoundExpressionStatement *statement);
    void EvaluateVariableDeclaration(BoundVariableDeclaration *variable);

private:
    SharedVariableMap         Variables;
    SharedBoundBlockStatement Root;

    SharedObject LastValue;
};
